home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume91 / utilitys / beav_132 / part03 / extend.c < prev    next >
C/C++ Source or Header  |  1991-11-13  |  11KB  |  509 lines

  1. /*
  2. *   Extended (M-X) commands.
  3. */
  4. #include    "def.h"
  5.  
  6. extern    char    MSG_not_now[];
  7. extern    char    MSG_func[];
  8. extern    char    MSG_unk_func[];
  9. extern    char    MSG_cmd_t_ex[];
  10. extern    char    MSG_unk_ext[];
  11. extern    char    MSG_d_b[];
  12. extern    char    MSG_unbd[];
  13. extern    char    MSG_bnd_to[];
  14. extern    char    MSG_ins_self[];
  15. extern    char    MSG_bnd_file[];
  16. extern    char    MSG_bld_wall[];
  17. extern    char    MSG_wall_head[];
  18. extern    char    MSG_beavrc[];
  19. extern    char    MSG_null[];
  20.  
  21.  
  22. #ifdef CUSTOMIZE 
  23.  
  24. char *flook();
  25.  
  26. static char *bindnm =
  27. {
  28.     0
  29. };                              /* file name for customized key bindings */
  30. #endif 
  31.  
  32. /*
  33. * This function modifies the keyboard
  34. * binding table, by adjusting the entries in the
  35. * big "bindings" array. Most of the grief deals with the
  36. * prompting for additional arguments. This code does not
  37. * work right if there is a keyboard macro floating around.
  38. * Should be fixed.
  39. */
  40. bool bindtokey ()
  41. {
  42.  
  43.     register int    s;
  44.     register    SYMBOL * sp;
  45.     register int    c;
  46.     char    xname[NXNAME];
  47. #ifdef CUSTOMIZE
  48.     char    xname2[NXNAME];
  49. #endif 
  50.  
  51.     if (kbdmip != NULL || kbdmop != NULL)
  52.     {
  53.         writ_echo (MSG_not_now);
  54.         return (FALSE);
  55.     }
  56.  
  57.     if ((s = eread (MSG_func, xname, NXNAME, EFAUTO, NULL)) != TRUE)
  58.         return (s);
  59.     if ((sp = symlookup (xname)) == NULL)
  60.     {
  61.         writ_echo (MSG_unk_func);
  62.         return (FALSE);
  63.     }
  64.  
  65. #ifdef CUSTOMIZE
  66.     strcpy (xname2, xname);
  67. #endif 
  68.     eputc (' ');
  69.     eputc ('K');
  70.     eputc ('e');
  71.     eputc ('y');
  72.     eputc (':');
  73.     eputc (' ');
  74.     ttflush ();
  75.     c = getkey ();              /* Read key.        */
  76.     keyname (xname, c);         /* Display keyname. */
  77.     eputs (xname);
  78.     ttflush ();
  79.     if (binding[c] != NULL)     /* Unbind old, and  */
  80.         --binding[c] -> s_nkey;
  81.     binding[c] = sp;            /* rebind new.      */
  82.     ++sp -> s_nkey;
  83.     sp -> s_modify |= SBOUND;    /* flag as altered key binding */
  84.  
  85.     return (TRUE);
  86. }
  87.  
  88.  
  89. /*
  90. * Extended command. Call the message line
  91. * routine to read in the command name and apply autocompletion
  92. * to it. When it comes back, look the name up in the symbol table
  93. * and run the command if it is found and has the right type.
  94. * Print an error if there is anything wrong.
  95. */
  96. char    extend (f, n, k)
  97. {
  98.  
  99.     register    SYMBOL * sp;
  100.     register char   s;
  101.     char    xname[NXNAME];
  102.  
  103.     if ((s = eread (MSG_cmd_t_ex, xname, NXNAME, EFNEW | EFAUTO, NULL)) != TRUE)
  104.         return (s);
  105.     if ((sp = symlookup (xname)) != NULL)
  106.         return ((*sp -> s_funcp) (f, n, KRANDOM));
  107.     writ_echo (MSG_unk_ext);
  108.     return (ABORT);
  109. }
  110.  
  111.  
  112. /*
  113. * Read a key from the keyboard, and look it
  114. * up in the binding table. Display the name of the function
  115. * currently bound to the key. Say that the key is not bound
  116. * if it is indeed not bound, or if the type is not a
  117. * "builtin". This is a bit of overkill, because this is the
  118. * only kind of function there is.
  119. */
  120. bool help ()
  121. {
  122.     register    SYMBOL * sp;
  123.     register int    c;
  124.     char    b[20];
  125.     char    buf[80];
  126.  
  127.     writ_echo (MSG_d_b);
  128.  
  129.     c = getkey ();
  130.     keyname (b, c);
  131.     if ((sp = binding[c]) == NULL)
  132.     {
  133.         sprintf (buf, MSG_unbd, b);
  134.         writ_echo (buf);
  135.     }
  136.     else
  137.     {
  138.         sprintf (buf, MSG_bnd_to, b, sp -> s_name);
  139.         writ_echo (buf);
  140.     }
  141.     return (TRUE);
  142. }
  143.  
  144. /*
  145. *   Sort the lines in the buffer.
  146. */
  147. void    sort_buf (b_ptr, cnt)
  148. BUFFER  *b_ptr;
  149. int     cnt;
  150. {
  151.     LINE    *lp1, *lp2;
  152.     bool    no_swap;
  153.     int     loop1, loop2;
  154.  
  155.     for (loop1 = cnt; loop1 > 0; loop1--)
  156.     {
  157.         no_swap = TRUE;
  158.         lp1 = b_ptr -> b_linep -> l_fp; /* point to first line */
  159.         lp2 = lp1 -> l_fp;      /* point to next line */
  160.         for (loop2 = 0; loop2 <= loop1; loop2++)
  161.         {
  162.             /* compare strings and swap if necessary */
  163.             if (0 < strcmp (&lp1 -> l_text[HFUNCCOL], &lp2 -> l_text[HFUNCCOL]))
  164.             {
  165.                 lp1 -> l_bp -> l_fp = lp2;  /* get pointer to first string */
  166.                 lp2 -> l_fp -> l_bp = lp1;  /* make it point to second string */
  167.  
  168.                 lp1 -> l_fp = lp2 -> l_fp;
  169.                 lp2 -> l_bp = lp1 -> l_bp;
  170.  
  171.                 lp1 -> l_bp = lp2;
  172.                 lp2 -> l_fp = lp1;
  173.  
  174.                 lp2 -> l_file_offset = lp1 -> l_file_offset;
  175.                 lp1 -> l_file_offset = lp2 -> l_file_offset + lp2 -> l_used;
  176.  
  177.                 no_swap = FALSE;
  178.             }
  179.             else
  180.             {
  181.                 /* if no swap then advance both pointers */
  182.                 lp1 = lp2;
  183.             }
  184.             lp2 = lp1 -> l_fp;
  185.         }
  186.         /* quick exit if sort is finished sooner than expected */
  187.         if (no_swap)
  188.         {
  189.             return;
  190.         }
  191.     }
  192. }
  193.  
  194. /*
  195. * This function creates a table, listing all
  196. * of the command keys and their current bindings, and stores
  197. * the table in the standard pop-op buffer (the one used by the
  198. * directory list command, the buffer list command, etc.). This
  199. * lets the editor produce it's own wall chart. The bindings to
  200. * "ins-self" are only displayed if there is an argument.
  201. */
  202. char    wallchart (f, n, k)
  203. {
  204.  
  205.     register char   s;
  206.     register int    key, i, j;
  207.     register    SYMBOL * sp;
  208.     register char  *cp1;
  209.     register char  *cp2;
  210.     char    buf[64];
  211.     WINDOW  *wp;
  212.  
  213.     if ((s = bclear (blistp)) != TRUE)/* Clear it out.    */
  214.         return (s);
  215.     i = 0;
  216.     (void) strcpy (blistp -> b_fname, MSG_null);
  217.     blistp -> b_flag = BFVIEW;
  218.     blistp -> b_type = BTHELP;
  219.     writ_echo (MSG_bld_wall);
  220.     sprintf (buf, MSG_wall_head);
  221.     if (addline (buf) == FALSE)
  222.         return(FALSE);
  223.     for (key = 0; key < NKEYS; ++key)
  224.     {
  225.         /* For all keys.    */
  226.         sp = binding[key];
  227.         if (sp != NULL &&
  228.             (f != FALSE || strcmp (sp -> s_name, MSG_ins_self) != 0))
  229.         {
  230.             cp1 = &buf[0];
  231.             while (cp1 < &buf[HFUNCCOL])/* Goto column 3.  */
  232.                 *cp1++ = ' ';
  233.             if ((sp -> s_modify & SBOUND) == 0)    /* comment out default binding */
  234.                 buf[0] = '#';
  235.             cp2 = sp -> s_name; /* Add function name.   */
  236.             while (*cp1++ = *cp2++)
  237.                 ;
  238.             cp1--;
  239.             while (cp1 < &buf[HKEY])/* Goto column 32.  */
  240.                 *cp1++ = ' ';
  241.             keyname (&buf[HKEY], key);
  242.             cp1 = &buf[strlen(buf)];
  243.             while (cp1 < &buf[HKEYCODE])/* Goto column 50.  */
  244.                 *cp1++ = ' ';
  245.             sprintf (&buf[HKEYCODE], "%4X", key);
  246.             if (addline (buf) == FALSE)
  247.                 break; /* lets go with what we have */
  248.             i++;
  249.         }
  250.     }
  251.  
  252.     /* list unbound functions lest they get lost */
  253.     for (j = 0; j < NSHASH; j++)
  254.     {
  255.         sp = symbol[j];
  256.         while (sp != NULL)
  257.         {
  258.             if (sp -> s_nkey == 0)
  259.             {
  260.                 cp1 = &buf[0];
  261.                 while (cp1 < &buf[HFUNCCOL])/* Goto column 3.  */
  262.                     *cp1++ = ' ';
  263.                 buf[0] = '#';
  264.                 cp2 = sp -> s_name; /* Add function name.   */
  265.                 while (*cp1++ = *cp2++)
  266.                     ;
  267.                 cp1--;
  268.                 while (cp1 < &buf[HENDCOL])
  269.                     *cp1++ = ' ';
  270.                 *cp1 = 0;
  271.                 i++;
  272.                 if (addline (buf) == FALSE)
  273.                     break; /* lets go with what we have */
  274.             }
  275.             sp = sp -> s_symp;
  276.         }
  277.     }
  278.     sort_buf (blistp, i);      /* sort buffer lines */
  279.     popblist ();
  280.     writ_echo (MSG_null);
  281.     /* make new window the current window */
  282.     wp = wheadp;
  283.     while (wp != NULL)
  284.     {
  285.         if (wp -> w_bufp == blistp)
  286.         {
  287.             curwp = wp;
  288.             curbp = wp -> w_bufp;
  289.             return (TRUE);
  290.         }
  291.         wp = wp -> w_wndp;
  292.     }
  293.     return (TRUE);
  294. }
  295.  
  296. /* check for BEAVFIL and read it in if found
  297. * - also, set local file variable for bindtokey for saving new defs
  298. * (this is some what of a hack as it only handles 'bindtokey' changes at 
  299. * this time - also local file io !!!)
  300. */
  301. void check_extend (sfname)
  302.  
  303. char *sfname;    /* name of startup file (null if default) */
  304.  
  305. {
  306.     char *fname;    /* resulting file name to execute */
  307.     char    rc_name[NFILEN];    /* fixed up name of rc file */
  308.     char    *term;
  309.     char *getenv();
  310.     register    SYMBOL * sp;
  311.     char    funcname[NXNAME + 1];
  312.     char    keybind[NXNAME + 1];
  313.     int     keyval;
  314.     FILE * bindf;
  315.  
  316.     /* look up the startup file */
  317.     if ((sfname != NULL) && (*sfname != 0))
  318.         fname = flook(sfname, TRUE);
  319.     else
  320.     {
  321. #ifdef UNIX
  322.         /* hidden file under unix */
  323.         strcpy (&rc_name[0], ".");
  324.         strcpy (&rc_name[1], MSG_beavrc);
  325.  
  326.         if ((term = getenv("TERM")) != 0)
  327.         {
  328.             strcpy (&rc_name[strlen(rc_name)], ".");
  329.             strcpy (&rc_name[strlen(rc_name)], term);
  330.         }
  331.         fname = flook(rc_name, TRUE);
  332.         /* if fixed up name is not there then check original */
  333.         if (fname == NULL)
  334.         {
  335.             /* hidden file under unix */
  336.             strcpy (&rc_name[0], ".");
  337.             strcpy (&rc_name[1], MSG_beavrc);
  338.             fname = flook(rc_name, TRUE);
  339.         }
  340. #else
  341.         strcpy (rc_name, MSG_beavrc);
  342.         fname = flook(rc_name, TRUE);
  343. #ifdef AMIGA
  344.         /* look for .beavrc in the current directory */
  345.         if(!fname) {
  346.             rc_name[0] = '.';
  347.             strcpy (&rc_name[1], MSG_beavrc);
  348.             fname = flook(rc_name, TRUE);
  349.         }
  350.         /* look for .beavrc in S: */
  351.         if(!fname) {
  352.             /* Have a look in startup directory */
  353.             rc_name[0] = 'S';
  354.             rc_name[1] = ':';
  355.             rc_name[2] = '.';
  356.             strcpy (&rc_name[3], MSG_beavrc);
  357.             fname = flook(rc_name, TRUE);
  358.         }
  359. #endif /* AMIGA */
  360. #endif
  361.     }
  362.     /* if it isn't around, don't sweat it */
  363.     if (fname == NULL)
  364.         return;
  365.  
  366.     if (bindf = fopen(fname, "r"))
  367.     {
  368.         char    buffr[80];
  369.         char    *buffp;
  370.  
  371.         buffp = buffr;
  372.         while (fread (buffp++, sizeof(char), 1, bindf) == 1)
  373.         {
  374.             /* scanf is unhappy with commas */
  375.             if (buffp[-1] == ',')
  376.                 buffp[-1] = '-';
  377.  
  378.             /* did we get a whole line */
  379.             if (buffp[-1] == '\n')
  380.             {
  381.                 *buffp = 0;    /* terminate line */
  382.                 buffp = buffr;
  383.                 sscanf (buffr, "%s %s %x", funcname, keybind, &keyval);
  384.                 if ((buffr[0] == '#') || (keyval == 0))
  385.                     continue;
  386.                 if (sp = symlookup (funcname))
  387.                 {
  388.                     if (binding[keyval] != NULL)/* Unbind old, and  */
  389.                         --binding[keyval] -> s_nkey;
  390.                     binding[keyval] = sp;/* rebind new.      */
  391.                     ++sp -> s_nkey;
  392.                     sp -> s_modify |= SBOUND;    /* flag as altered key binding */
  393.                 }
  394.             }
  395.         }
  396.         fclose (bindf);
  397.     }
  398. }
  399.  
  400. /*    Look up the existance of a file along the normal or PATH
  401.     environment variable. Look first in the HOME directory if
  402.     asked and possible
  403. */
  404.  
  405. char *flook(fname, hflag)
  406.  
  407. char *fname;    /* base file name to search for */
  408. int hflag;    /* Look in the HOME environment variable first? */
  409.  
  410. {
  411.     register char *home;    /* path to home directory */
  412.     register char *path;    /* environmental PATH variable */
  413.     register char *sp;    /* pointer into path spec */
  414.     register int i;        /* index */
  415.     static char fspec[NFILEN * 2];    /* full path spec to search */
  416.     char *getenv();
  417.     FILE * bindf;
  418.  
  419.     if (hflag) {
  420.         home = getenv("HOME");
  421.         if (home != NULL) {
  422.             /* build home dir file spec */
  423.             strcpy(fspec, home);
  424.             if (fspec[strlen(fspec) - 1] != '/')
  425.                 strcat(fspec, "/");
  426.             strcat(fspec, fname);
  427.  
  428.             /* and try it out */
  429.             if (bindf = fopen(fspec, "r"))
  430.             {
  431.                 fclose(bindf);
  432.                 return(fspec);
  433.             }
  434.         }
  435.     }
  436.  
  437.     /* always try the current directory first */
  438.     if (bindf = fopen(fname, "r"))
  439.     {
  440.         fclose(bindf);
  441.         return(fname);
  442.     }
  443.  
  444.     /* get the PATH variable */
  445.     path = getenv("PATH");
  446.     if (path != NULL)
  447.         while (*path) {
  448.  
  449.             /* build next possible file spec */
  450.             sp = fspec;
  451.             while (*path && (*path != PATHCHR))
  452.                 *sp++ = *path++;
  453.  
  454.             /* add a terminating dir separator if we need it */
  455.             if (sp[-1] != SEPCHAR)
  456.                 *sp++ = SEPCHAR;
  457.  
  458.             *sp = 0;
  459.             strcat(fspec, fname);
  460.  
  461.             /* and try it out */
  462.             if (bindf = fopen(fspec, "r"))
  463.             {
  464.                 fclose(bindf);
  465.                 return(fspec);
  466.             }
  467.  
  468.             if (*path == PATHCHR)
  469.                 ++path;
  470.         }
  471.  
  472.     return(NULL);    /* no such luck */
  473. }
  474.  
  475.  
  476. /* interactive method for loading binding file
  477. * (uses above routine, obviously)
  478. */
  479. char    load_extend ()
  480. {
  481.  
  482. #ifdef CUSTOMIZE
  483.     register char   s;
  484.     char    fname[NFILEN];
  485.  
  486.     if ((s = ereply (MSG_bnd_file, fname, NFILEN, NULL)) != TRUE)
  487.         return (s);
  488.     check_extend (fname);
  489.     writ_echo (okmsg);
  490. #endif
  491.     return (TRUE);
  492. }
  493.  
  494. int     find_keyval (name)
  495. char   *name;
  496. {
  497.     SYMBOL * sp;
  498.     int     key;
  499.  
  500.     for (key = 0; key < NKEYS; ++key)
  501.     {
  502.         /* For all keys.    */
  503.         sp = binding[key];
  504.         if (sp != NULL && (strcmp (sp -> s_name, name) == 0))
  505.             return (key);
  506.     }
  507.     return (0);
  508. }
  509.